package com.sea.base.ext.view

import android.view.MotionEvent
import android.view.View
import androidx.annotation.Px
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import com.sea.base.R
import com.sea.base.ext.global.dp
import com.sea.base.utils.SpacesItemDecoration
import kotlin.math.abs

/**
 * rv点击事件拓展
 * @param listener null表示删除
 */
fun RecyclerView.setOnClickListenerByTouch(listener: View.OnClickListener?) {
    //删除以前的
    getTypeTag<RecyclerView.OnItemTouchListener>(R.id.tag_rv_click)?.let {
        removeOnItemTouchListener(it)
    }
    setOnClickListener(listener)

    if (listener == null) {
        return
    }
    val newListener = object : RecyclerView.OnItemTouchListener {
        private var downX = 0f
        private var downY = 0f
        override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
            when (e.action) {
                MotionEvent.ACTION_UP -> {
                    val upX = e.x
                    val upY = e.y
                    if (abs(upX - downX) < 10.dp && abs(upY - downY) < 10.dp && e.eventTime - e.downTime < 500) {
                        performClick()
                    }
                }

                MotionEvent.ACTION_DOWN -> {
                    downX = e.x
                    downY = e.y
                }
            }
            return false
        }

        override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
        override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
    }
    addOnItemTouchListener(newListener)
    setTag(R.id.tag_rv_click, newListener)
}

/**
 * 如果class相等则删除旧的（主要用于复用里的rv）
 * [SpacesItemDecoration]、[setAdapterSpacesItemDecoration]
 */
fun RecyclerView.replaceItemDecorationWithClass(decor: RecyclerView.ItemDecoration) {
    if (itemDecorationCount > 0) {
        ((itemDecorationCount - 1)..0).forEach {
            val oldDecor = getItemDecorationAt(it)
            if (oldDecor == decor) {
                //完全相等就不需要重复设置了
                return
            }
            if (oldDecor.javaClass == decor.javaClass) {
                removeItemDecorationAt(it)
            }
        }
    }
    addItemDecoration(decor)
}

/**
 * 设置Adapter Item的间隔
 * 注意：暂时没有处理header、footer，后续需要时添加
 * 由于这里是压缩view大小，所以对于类似FlexboxLayoutManager这种view本身是Wrap的可能会出现压缩变形的情况，所以不支持
 * 如果效果不太好，你可以使用rv的margin+item的margin来实现
 */
fun RecyclerView.setAdapterSpacesItemDecoration(@Px horizontalSpace: Int, @Px verticalSpace: Int = horizontalSpace, isLastSpace: Boolean = true) {
    replaceItemDecorationWithClass(SpacesItemDecoration(horizontalSpace, verticalSpace, isLastSpace))
}

inline fun RecyclerView.addOnScrollListener(
    crossinline onStateChangedCall: OnScrollListener.(newState: Int) -> Unit = {},
    crossinline onScrolledCall: OnScrollListener.(dx: Int, dy: Int) -> Unit = { _, _ -> },
) {
    addOnScrollListener(object : OnScrollListener() {
        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)
            this.onStateChangedCall(newState)
        }

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)
            this.onScrolledCall(dx, dy)
        }
    })
}

/**
 * 用户是否可滑动
 * 如果为false，目前会拦截所以的事件，子view也无法响应任何事件
 */
var RecyclerView.isScrollable: Boolean
    get() = getTypeTag<RecyclerView.OnItemTouchListener>(R.id.tag_rv_scrollable_intercept) == null
    set(value) {
        if (value) {
            //删除以前的
            getTypeTag<RecyclerView.OnItemTouchListener>(R.id.tag_rv_scrollable_intercept)?.let {
                removeOnItemTouchListener(it)
            }
        } else {
            if (!isScrollable) {
                return
            }
            val newListener = object : RecyclerView.OnItemTouchListener {
                override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent) = true
                override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
                override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
            }
            addOnItemTouchListener(newListener)
            setTag(R.id.tag_rv_scrollable_intercept, newListener)
        }
    }

/**
 * 如果有就直接返回，如果没有就创建并设置，一般用于被嵌套的RecyclerView中
 */
inline fun <reified T : RecyclerView.Adapter<*>> RecyclerView.getAdapterOrCreate(createCallback: () -> T): T {
    return (adapter as? T) ?: createCallback.invoke().also { adapter = it }
}

/**
 * 如果有就直接返回，如果没有就创建并设置，一般用于被嵌套的RecyclerView中
 */
inline fun <reified T : RecyclerView.LayoutManager> RecyclerView.getLayoutManagerOrCreate(createCallback: () -> T): T {
    return (layoutManager as? T) ?: createCallback.invoke().also { layoutManager = it }
}

/**
 * 设置[GridLayoutManager]的spanSizeLookup，如果不是GridLayoutManager则会直接崩溃
 */
inline fun RecyclerView.setGridLayoutManagerSpanSizeLookup(crossinline createCallback: (absPosition: Int) -> Int) {
    (this.layoutManager as GridLayoutManager).spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
        override fun getSpanSize(position: Int) = createCallback.invoke(position)
    }
}